﻿using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;

using Inspire.Main.UIElements;
using Inspire.Classes.Interfaces;

namespace Inspire
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window, INavHost
    {
        /// <summary>
        /// Specifies the first pageIndex loaded.
        /// </summary>
        private string _HomePage = "Pages\\Home.xaml";

        /// <summary>
        /// _PageMap stores the object of each pageIndex so that user work is not lost during navigation.
        /// </summary>
        private Dictionary<String, Page> _PageMap = new Dictionary<String, Page>();

        /// <summary>
        /// The Main Navigation Menu
        /// </summary>
        private NavStackPanel _NavigationMenu;

        /// <summary>
        /// Frame to display pages.
        /// </summary>
        private Frame ContentArea;

        public MainWindow()
        {
            InitializeComponent();

            // Build the navigation menu
            this._NavigationMenu = new NavStackPanel(0, 0, this);
            
                // Create First NavExpander (Main)
                NavExpander subMenu1 = new NavExpander("Main Menu", this._NavigationMenu);

                AddPageToMap("Pages\\Home.xaml");
                subMenu1.AddButton(new NavButton("Home", "Pages\\Home.xaml", "GrayButtonStyle", subMenu1));
                subMenu1.AddButton(new NavButton("Borrow", "Pages\\Borrow.xaml", "GrayButtonStyle", subMenu1));
                subMenu1.AddButton(new NavButton("Return", "Pages\\Return.xaml", "GrayButtonStyle", subMenu1));
                
                // Create Second NavExpander (Patrons)
                NavExpander subMenu2 = new NavExpander("Patrons", this._NavigationMenu);
                
                AddPageToMap("Pages\\SearchPatrons.xaml");
                subMenu2.AddButton(new NavButton("Search", "Pages\\SearchPatrons.xaml", "GrayButtonStyle", subMenu2));
                
                AddPageToMap("Pages\\AddPatrons.xaml");
                subMenu2.AddButton(new NavButton("Add", "Pages\\AddPatrons.xaml", "GrayButtonStyle", subMenu2));

                // Create Third NavExpander (Items)
                NavExpander subMenu3 = new NavExpander("Items", this._NavigationMenu);
                subMenu3.AddButton(new NavButton("Search", "Pages\\SearchItems.xaml", "GrayButtonStyle", subMenu3));
                subMenu3.AddButton(new NavButton("Add", "Pages\\AddItems.xaml", "GrayButtonStyle", subMenu3));

                // Create Fourth NavExpander (Resources)
                NavExpander subMenu4 = new NavExpander("Resources", this._NavigationMenu);
                subMenu4.AddButton(new NavButton("Search", "Pages\\SearchResources.xaml", "GrayButtonStyle", subMenu4));
                subMenu4.AddButton(new NavButton("Add", "Pages\\AddResources.xaml", "GrayButtonStyle", subMenu4));

                // Create Fifth NavExpander (Reports)
                NavExpander subMenu5 = new NavExpander("Reports", this._NavigationMenu);
                subMenu5.AddButton(new NavButton("Library Cards", "Pages\\LibraryCardsReports.xaml", "GrayButtonStyle", subMenu5));
                subMenu5.AddButton(new NavButton("Item", "Pages\\ItemReports.xaml", "GrayButtonStyle", subMenu5));
                subMenu5.AddButton(new NavButton("Resource", "Pages\\ResourceReports.xaml", "GrayButtonStyle", subMenu5));
                subMenu5.AddButton(new NavButton("Circulation", "Pages\\CirculationReports.xaml", "GrayButtonStyle", subMenu5));
                subMenu5.AddButton(new NavButton("Patron", "Pages\\PatronReports.xaml", "GrayButtonStyle", subMenu5));
                
                // Create Sixth NavExpander (Administration)
                NavExpander subMenu6 = new NavExpander("Administration", this._NavigationMenu);
                AddPageToMap("Pages\\CustomFieldTypes.xaml");
                subMenu6.AddButton(new NavButton("Custom Field Types", "Pages\\CustomFieldTypes.xaml", "GrayButtonStyle", subMenu6));
                subMenu6.AddButton(new NavButton("Library Info.", "Pages\\LibraryInfo.xaml", "GrayButtonStyle", subMenu6));
                subMenu6.AddButton(new NavButton("Employees", "Pages\\Employees.xaml", "GrayButtonStyle", subMenu6));

            this._NavigationMenu.AddNavExpander(subMenu1);
            this._NavigationMenu.AddNavExpander(subMenu2);
            this._NavigationMenu.AddNavExpander(subMenu3);
            this._NavigationMenu.AddNavExpander(subMenu4);
            this._NavigationMenu.AddNavExpander(subMenu5);
            this._NavigationMenu.AddNavExpander(subMenu6);

            this.NavigationGrid.Children.Add(this._NavigationMenu);

            // Initialize the Main Button to be disabled for the Home Page
            this.PropogateNavUp(this._HomePage);
            this.PropogateNavDown(this._HomePage);
        }

        /// <summary>
        /// Load the pageIndex requested by the user via the navigation menu.
        /// </summary>
        /// <param name="navigationUri">The URI request represented by a button in the navigation menu.</param>
        public void PropogateNavUp(string navigationUri)
        {
            this.LoadURI(navigationUri);
        }

        /// <summary>
        /// Propogate the requested URI down the navigation menu to synchronize it with a shortcut
        /// the user clicked on.
        /// </summary>
        /// <param name="navigationUri">The URI of the shortcut the user clicked on.</param>
        public void PropogateNavDown(string navigationUri)
        {
            this._NavigationMenu.PropogateNavDown(navigationUri);
        }

        /// <summary>
        /// Change the source of the main Frame to a requested URI. The request is most likely the result
        /// of the user clicking on a shortcut at the top of the pageIndex or a NavButton in the navigation menu.
        /// </summary>
        /// <param name="navigationUri"></param>
        private void LoadURI(string navigationUri)
        {
            Uri nextPage = new Uri(navigationUri, UriKind.Relative);

            // Check to see if the URI is valid
            if (this.ResourceExists(nextPage))
            {
                // Check to see if it has already been navigated to
                if (this._PageMap.ContainsKey(navigationUri))
                {
                    //
                    // To stop the "Clicking" sound, we must recreate the Frame
                    // and add it back into the main Grid every time the user navigates
                    //
                    if (this.NavigationGrid.Children.Contains(this.ContentArea))
                    {
                        this.NavigationGrid.Children.Remove(this.ContentArea);
                    }
                    this.ContentArea = null;
                    this.ContentArea = new Frame();
                    this.ContentArea.HorizontalAlignment = HorizontalAlignment.Stretch;
                    this.ContentArea.VerticalAlignment = VerticalAlignment.Stretch;
                    Grid.SetColumn(this.ContentArea, 1);
                    Grid.SetRow(this.ContentArea, 0);
                    this.ContentArea.Content = this._PageMap[navigationUri].Content;
                    ((IPage)this._PageMap[navigationUri]).Page_Displayed();

                    // Add the Frame back in with the new pageIndex loaded
                    this.NavigationGrid.Children.Add(this.ContentArea);
                }
                else
                {
                    // Create the new Page object and add it to _PageMap
                    this._PageMap.Add(navigationUri, (Page)Application.LoadComponent(nextPage));

                    //
                    // To stop the "Clicking" sound, we must recreate the Frame
                    // and add it back into the main Grid every time the user navigates
                    //
                    if (this.NavigationGrid.Children.Contains(this.ContentArea))
                    {
                        this.NavigationGrid.Children.Remove(this.ContentArea);
                    }
                    this.ContentArea = null;
                    this.ContentArea = new Frame();
                    this.ContentArea.HorizontalAlignment = HorizontalAlignment.Stretch;
                    this.ContentArea.VerticalAlignment = VerticalAlignment.Stretch;
                    Grid.SetColumn(this.ContentArea, 1);
                    Grid.SetRow(this.ContentArea, 0);
                    this.ContentArea.Content = this._PageMap[navigationUri].Content;
                    ((IPage)this._PageMap[navigationUri]).Page_Displayed();

                    // Add the Frame back in with the new pageIndex loaded
                    this.NavigationGrid.Children.Add(this.ContentArea);
                }
            }
        }

        /// <summary>
        /// Add the Page to the Page Map.
        /// </summary>
        /// <param name="relativeUri"></param>
        private void AddPageToMap(string relativeUri)
        {
            Uri newUri = new Uri(relativeUri, UriKind.Relative);

            if (this.ResourceExists(newUri))
            {
                // Create the new Page object and add it to the Page Map.
                this._PageMap.Add(relativeUri, (Page)Application.LoadComponent(newUri));
            }
        }


        /// <summary>
        /// Check if the resource specified by a URI exists.
        /// </summary>
        /// <param name="navigationUri">URI resource to check.</param>
        /// <returns>true if the resource exists; false, otherwise.</returns>
        private bool ResourceExists(Uri navigationUri)
        {
            /*
             * This pragma stops the compiler warning "Variable 'e' is delcared but never used
             */
            #pragma warning disable 0168
            try
            {
                return Application.GetResourceStream(navigationUri) != null;
            }
            catch (System.IO.IOException e)
            {
                return false;
            }
            #pragma warning restore 0168
        }

        /// <summary>
        /// Event Handler for Close Button.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ExitButton_Click(object sender, RoutedEventArgs e)
        {
            Application.Current.Shutdown();
        }

        /// <summary>
        /// Load the Resources Window
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ItemsButton_Click(object sender, RoutedEventArgs e)
        {
            this.PropogateNavDown("Pages\\SearchItems.xaml");
            this.LoadURI("Pages\\SearchItems.xaml");
        }

        /// <summary>
        /// Load the Resources Window
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ResourcesButton_Click(object sender, RoutedEventArgs e)
        {
            this.PropogateNavDown("Pages\\SearchResources.xaml");
            this.LoadURI("Pages\\SearchResources.xaml");
        }

        /// <summary>
        /// Load the Patron Window
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void PatronButton_Click(object sender, RoutedEventArgs e)
        {
            this.PropogateNavDown("Pages\\SearchPatrons.xaml");
            this.LoadURI("Pages\\SearchPatrons.xaml");
        }

        /// <summary>
        /// Load the Home Window
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void HomeButton_Click(object sender, RoutedEventArgs e)
        {
            this.PropogateNavDown("Pages\\Home.xaml");
            this.LoadURI("Pages\\Home.xaml");
        }

    }
}
